import { Injectable } from '@nestjs/common';
import { ResourceInfo, ResourceManifest, ProjectExportWithResources } from '../types/resource.types';
import { cdnDomain } from '@/config/domain';
import * as fs from 'fs';
import * as path from 'path';

@Injectable()
export class ResourceManifestService {

  /**
   * 创建资源清单
   */
  createManifest(
    resources: ResourceInfo[],
    downloadedResources: ResourceInfo[],
    originalCdnDomain: string = cdnDomain
  ): ResourceManifest {
    const total = resources.length;
    const downloaded = downloadedResources.length;
    const cdn = resources.filter(r => r.source === 'cdn').length;
    const external = resources.filter(r => r.source === 'external').length;

    return {
      total,
      downloaded,
      external,
      cdn,
      files: downloadedResources,
      originalCdnDomain,
      newCdnDomain: cdnDomain, // 当前环境的CDN域名
    };
  }

  /**
   * 创建包含资源的项目导出数据
   */
  createExportDataWithResources(
    baseExportData: any,
    resourceManifest: ResourceManifest
  ): ProjectExportWithResources {
    return {
      ...baseExportData,
      version: '2.0.0', // 更新版本号以支持资源
      resources: resourceManifest,
    };
  }

  /**
   * 保存资源清单到文件
   */
  saveManifest(manifest: ResourceManifest, tempDir: string): void {
    const manifestPath = path.join(tempDir, 'resources', 'manifest.json');

    // 确保目录存在
    const manifestDir = path.dirname(manifestPath);
    if (!fs.existsSync(manifestDir)) {
      fs.mkdirSync(manifestDir, { recursive: true });
    }

    fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');

    // 同时保存一份到根目录，方便导入时查找
    const rootManifestPath = path.join(tempDir, 'resource-manifest.json');
    fs.writeFileSync(rootManifestPath, JSON.stringify(manifest, null, 2), 'utf8');
  }

  /**
   * 从文件读取资源清单
   */
  loadManifest(tempDir: string): ResourceManifest | null {
    try {
      const manifestPath = path.join(tempDir, 'resources', 'manifest.json');

      if (!fs.existsSync(manifestPath)) {
        return null;
      }

      const content = fs.readFileSync(manifestPath, 'utf8');
      return JSON.parse(content);
    } catch (error) {
      console.error('读取资源清单失败:', error);
      return null;
    }
  }

  /**
   * 验证资源完整性
   */
  validateResources(manifest: ResourceManifest, tempDir: string): {
    valid: boolean;
    missingFiles: string[];
    extraFiles: string[];
  } {
    const missingFiles: string[] = [];
    const extraFiles: string[] = [];

    // 检查清单中的文件是否存在
    manifest.files.forEach(resource => {
      const filePath = path.join(tempDir, resource.localPath);
      if (!fs.existsSync(filePath)) {
        missingFiles.push(resource.localPath);
      }
    });

    // 检查是否有额外的文件（可选）
    const resourcesDir = path.join(tempDir, 'resources');
    if (fs.existsSync(resourcesDir)) {
      const allFiles = this.getAllFiles(resourcesDir);
      const expectedFiles = new Set(
        manifest.files.map(r => path.join(tempDir, r.localPath))
      );

      allFiles.forEach(file => {
        if (!expectedFiles.has(file) && file !== path.join(tempDir, 'resources', 'manifest.json')) {
          extraFiles.push(path.relative(tempDir, file));
        }
      });
    }

    return {
      valid: missingFiles.length === 0,
      missingFiles,
      extraFiles,
    };
  }

  /**
   * 递归获取所有文件
   */
  private getAllFiles(dir: string): string[] {
    const files: string[] = [];

    function traverse(currentDir: string) {
      const items = fs.readdirSync(currentDir);

      items.forEach(item => {
        const fullPath = path.join(currentDir, item);
        const stat = fs.statSync(fullPath);

        if (stat.isDirectory()) {
          traverse(fullPath);
        } else {
          files.push(fullPath);
        }
      });
    }

    traverse(dir);
    return files;
  }

  /**
   * 更新资源清单中的URL映射
   */
  updateResourceUrls(
    manifest: ResourceManifest,
    urlMapping: Map<string, string>
  ): ResourceManifest {
    const updatedFiles = manifest.files.map(resource => {
      const newUrl = urlMapping.get(resource.originalUrl);
      if (newUrl) {
        return {
          ...resource,
          originalUrl: newUrl, // 更新为新的URL
        };
      }
      return resource;
    });

    return {
      ...manifest,
      files: updatedFiles,
    };
  }

  /**
   * 生成资源统计报告
   */
  generateReport(manifest: ResourceManifest): string {
    const report = [
      '=== 资源处理报告 ===',
      `总计: ${manifest.total} 个资源`,
      `已下载: ${manifest.downloaded} 个`,
      `CDN资源: ${manifest.cdn} 个`,
      `外部资源: ${manifest.external} 个`,
      `原CDN域名: ${manifest.originalCdnDomain}`,
      `新CDN域名: ${manifest.newCdnDomain}`,
      '',
      '=== 资源分类 ===',
    ];

    // 按类型统计
    const typeStats = manifest.files.reduce((acc, resource) => {
      acc[resource.type] = (acc[resource.type] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    Object.entries(typeStats).forEach(([type, count]) => {
      report.push(`${type}: ${count} 个`);
    });

    // 文件大小统计
    const totalSize = manifest.files.reduce((acc, resource) => acc + (resource.size || 0), 0);
    report.push('');
    report.push(`总大小: ${this.formatFileSize(totalSize)}`);

    return report.join('\n');
  }

  /**
   * 格式化文件大小
   */
  private formatFileSize(bytes: number): string {
    const sizes = ['B', 'KB', 'MB', 'GB'];
    if (bytes === 0) return '0 B';

    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
  }
}